﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Security;
using System.Text.RegularExpressions;
using System.Configuration.Provider;
using System.Web.Configuration;
using System.Security.Cryptography;
using System.Configuration;
using System.Collections.Specialized;
using Domaine.Contracts;
using Domaine.Entity;
using Domaine.Core;
using Infrastructure.Data.Repository;
using Infrastructure.Data.UnitOfWork;
using Application.Membership.Resources;
using System.IO;
using Infrastructure.CrossCutting;

namespace Application.Services
{
    public class AppMembershipProvider :  IAppMembershipProvider
    {
        #region Const

        private const int PASSWORD_SIZE = 14;
        private const int SALT_SIZE_IN_BYTES = 16;

        #endregion


        #region Ctor

        public AppMembershipProvider(IMemberShipRepository memberShipRepository, IAspApplicationRepository aspApplicationRepository)
        {
            if (memberShipRepository == null)
                throw new ArgumentNullException("memberShipRepository");
            if (aspApplicationRepository == null)
                throw new ArgumentNullException("aspApplicationRepository");
            _aspApplicationRepository = aspApplicationRepository;
            _memberShipRepository = memberShipRepository;
            MembershipSection section = WebConfigurationManager.GetSection("system.web/membership") as MembershipSection;
            this.Initialize(section);
        }
        #endregion

        #region MembershipProvider
        #region Members

        IMemberShipRepository _memberShipRepository;
        IAspApplicationRepository _aspApplicationRepository;

        private bool _EnablePasswordReset;
        private bool _EnablePasswordRetrieval;
        private int _MaxInvalidPasswordAttempts;
        private int _MinRequiredNonAlphanumericCharacters;
        private int _MinRequiredPasswordLength;
        private int _PasswordAttemptWindow;
        private MembershipPasswordFormat _PasswordFormat;
        private string _PasswordStrengthRegularExpression;
        private bool _RequiresQuestionAndAnswer;
        private bool _RequiresUniqueEmail;
        private MembershipPasswordCompatibilityMode _LegacyPasswordCompatibilityMode;
        private string s_HashAlgorithm;
        #endregion



        #region Properties
        public  string ApplicationName { get; set; }
        public  bool EnablePasswordReset { get { return _EnablePasswordReset; } }
        public  bool EnablePasswordRetrieval { get { return _EnablePasswordRetrieval; } }
        public  int MaxInvalidPasswordAttempts { get { return _MaxInvalidPasswordAttempts; } }
        public  int MinRequiredNonAlphanumericCharacters { get { return _MinRequiredNonAlphanumericCharacters; } }
        public  int MinRequiredPasswordLength { get { return _MinRequiredPasswordLength; } }
        public  int PasswordAttemptWindow { get { return _PasswordAttemptWindow; } }
        public  System.Web.Security.MembershipPasswordFormat PasswordFormat { get { return _PasswordFormat; } }
        public  string PasswordStrengthRegularExpression { get { return _PasswordStrengthRegularExpression; } }
        public  bool RequiresQuestionAndAnswer { get { return _RequiresQuestionAndAnswer; } }
        public  bool RequiresUniqueEmail { get { return _RequiresUniqueEmail; } }
        
        #endregion

        
        #region Methods


        #region Initialize

        public void Initialize(MembershipSection config)
        {
            if (config == null)
                throw new ArgumentNullException("MembershipSection_config");
            _EnablePasswordRetrieval = GetConfigBooleanValue(config,"enablePasswordRetrieval", false);
            _EnablePasswordReset = GetConfigBooleanValue(config, "enablePasswordReset", true);
            _RequiresQuestionAndAnswer = GetConfigBooleanValue(config, "requiresQuestionAndAnswer", true);
            _RequiresUniqueEmail = GetConfigBooleanValue(config, "requiresUniqueEmail", true);
            _MaxInvalidPasswordAttempts = GetConfigIntValue(config, "maxInvalidPasswordAttempts", 5, false, 0);
            _PasswordAttemptWindow = GetConfigIntValue(config, "passwordAttemptWindow", 10, false, 0);
            _MinRequiredPasswordLength = GetConfigIntValue(config, "minRequiredPasswordLength", 7, false, 128);
            _MinRequiredNonAlphanumericCharacters = GetConfigIntValue(config, "minRequiredNonalphanumericCharacters", 1, true, 128);
            _PasswordStrengthRegularExpression = config.Providers[config.DefaultProvider].Parameters["passwordStrengthRegularExpression"];
            if (_PasswordStrengthRegularExpression != null)
            {
                _PasswordStrengthRegularExpression = _PasswordStrengthRegularExpression.Trim();
                if (_PasswordStrengthRegularExpression.Length != 0)
                {
                    try
                    {
                        Regex regex = new Regex(_PasswordStrengthRegularExpression);
                    }
                    catch (ArgumentException e)
                    {
                        throw new   ProviderException(e.Message, e);
                    }
                }
            }
            else
            {
                _PasswordStrengthRegularExpression = string.Empty;
            }
            if (_MinRequiredNonAlphanumericCharacters > _MinRequiredPasswordLength)
                throw new LMSException(Messages.MinRequiredNonalphanumericCharactersError);
            ApplicationName = GetConfigStringValue(config,"applicationName", "/");
            if (ApplicationName.Length > 256)
                throw new LMSException(Messages.ApplicationLengthError);
            string strTemp = GetConfigStringValue(config,"passwordFormat", "Hashed");
            switch (strTemp)
            {
                case "Clear": _PasswordFormat = MembershipPasswordFormat.Clear; break;
                case "Encrypted": _PasswordFormat = MembershipPasswordFormat.Encrypted; break;
                case "Hashed": _PasswordFormat = MembershipPasswordFormat.Hashed; break;
                default:
                    throw new LMSException(Messages.InvalidPasswordFormat);
            }
            if (PasswordFormat == MembershipPasswordFormat.Hashed && EnablePasswordRetrieval)
                throw new LMSException(Messages.PasswordHashedRetrieval);
            string passwordCompactMode =config.Providers[config.DefaultProvider].Parameters["passwordCompatMode"] ;
            if (!string.IsNullOrEmpty(passwordCompactMode))
            {
                this._LegacyPasswordCompatibilityMode = (MembershipPasswordCompatibilityMode)Enum.Parse(typeof(MembershipPasswordCompatibilityMode), passwordCompactMode);
            }

        }

        #endregion

        public  bool ChangePassword(string username, string oldPassword, string newPassword)
        {
            Domaine.Entity.Membership member = this._memberShipRepository.GetFilteredFullElements(u => u.User.UserName == username).FirstOrDefault();
            if (member == null) return false;
            var passwordFormat = member.PasswordFormat;
            var passwordSalt = member.PasswordSalt;
            var check = CheckPassword(member , oldPassword, passwordFormat, passwordSalt, false, false, true);
            if (!check)
            {
                this._memberShipRepository.Modify(member);
                this._memberShipRepository.UnitOfWork.Commit();
                return false;
            }
            if (PasswordFormat != passwordFormat)
            {
                passwordFormat = PasswordFormat;
                passwordSalt = GenerateSalt();
            }
            member.Password=EncodePassword(newPassword, passwordFormat, passwordSalt);
            member.LastPasswordChangedDate= DateTime.UtcNow;
            member.FailedPasswordAnswerAttemptCount= 0;
            member.FailedPasswordAttemptCount= 0;
            this._memberShipRepository.Modify(member);
            this._memberShipRepository.UnitOfWork.Commit();
            return true;
        }





        public  bool ChangePasswordQuestionAndAnswer(string username, string password, string newPasswordQuestion, string newPasswordAnswer)
        {
            Domaine.Entity.Membership member = this._memberShipRepository.GetFilteredFullElements(u => u.User.UserName == username).FirstOrDefault();
            if (member == null) return false;

            var passwordFormat = member.PasswordFormat;
            var passwordSalt = member.PasswordSalt;
            var check = CheckPassword(member,  password, passwordFormat, passwordSalt, false, false, true);
            if (!check)
            {
                this._memberShipRepository.Modify(member);
                this._memberShipRepository.UnitOfWork.Commit();
                return false;
            }
            member.PasswordQuestion=newPasswordQuestion;
            member.PasswordAnswer=EncodePassword(newPasswordAnswer.ToLower(), passwordFormat, passwordSalt);
            this._memberShipRepository.Modify(member);
            this._memberShipRepository.UnitOfWork.Commit();
            return true;
        }


        public Domaine.Entity.Membership AddNewMember(Domaine.Entity.Membership newMember)
        {

            if (newMember == null || newMember.User==null) return null;
            if (string.IsNullOrWhiteSpace(newMember.User.UserName))
            {
                throw new LMSException(Messages.InvalidUserName);
            }
            Guid providerKey = CreateMemberId(newMember.UserID);
            if (!IsValidEmail(newMember.Email))
            {
                throw new LMSException(Messages.InvalidEmail);
            }
            if (string.IsNullOrWhiteSpace(newMember.Password) || !checkMinAlphaNumericPassword(newMember.Password, this.MinRequiredNonAlphanumericCharacters))
            {
                throw new LMSException(Messages.InvalidPassword);
            }
            if (this.PasswordStrengthRegularExpression.Length > 0)
            {
                if (!Regex.IsMatch(newMember.Password, PasswordStrengthRegularExpression))
                {
                    throw new LMSException(Messages.InvalidPassword);
                }
            }
            if (this._memberShipRepository.GetFilteredFullElements(u => u.User.UserName == newMember.User.UserName).Any())
            {
                throw new LMSException(Messages.DuplicateUserName);
            }
            if (this._memberShipRepository.GetFilteredFullElements(u => u.Email == newMember.Email).Any())
            {
                throw new LMSException(Messages.DuplicateEmail);
            }
            var app = this._aspApplicationRepository.GetAll().FirstOrDefault();
            if (app == null)
            {
                app = new Domaine.Entity.AspApplication()
                {
                    ApplicationID = Guid.NewGuid(),
                    ApplicationName = "/",
                };
                this._aspApplicationRepository.Add(app);
            }
            var passwordSalt = GenerateSalt();
            var encodedPassword = EncodePassword(newMember.Password, PasswordFormat, passwordSalt);
            string question = "";
            string answer = "";
            if (newMember.PasswordAnswer != null)
            {
                var encodedAnswer = EncodeAnswerPassword(newMember.PasswordAnswer, PasswordFormat, passwordSalt);
                question = newMember.PasswordQuestion;
                answer = encodedAnswer;
            }
            var now = DateTime.UtcNow;
            Domaine.Entity.Membership newDbMember = new Domaine.Entity.Membership()
            {
                User = new Domaine.Entity.User()
                {
                    UserID = providerKey,
                    ApplicationID = app.ApplicationID,
                    UserName =newMember.User.UserName,
                    LastActivityDate = now,
                    IsAnonymous = false
                },
                UserID = providerKey,
                ApplicationID = app.ApplicationID,
                Email = newMember.Email,
                IsApproved = newMember.IsApproved,
                PasswordFormat = PasswordFormat,
                PasswordSalt = passwordSalt,
                Password = encodedPassword,
                PasswordQuestion = question,
                PasswordAnswer = answer,
                CreateDate = now,
                LastLockoutDate = now,
                LastLoginDate = now,
                LastPasswordChangedDate = now,
                FailedPasswordAttemptWindowStart = now,
                FailedPasswordAnswerAttemptWindowStart = now,
                IsLockedOut = false,
                Comment = ""
            };
            this._memberShipRepository.Add(newDbMember);
            this._memberShipRepository.UnitOfWork.Commit();
            return newMember;

        }


        public  bool RemoveMember(string username )
        {
            Domaine.Entity.Membership member = this._memberShipRepository.GetFilteredFullElements(u => u.User.UserName == username).FirstOrDefault();
            if (member == null) return false;
            try
            {
                this._memberShipRepository.Remove(member);
                this._memberShipRepository.UnitOfWork.Commit();
                return true;
            }
            catch
            {
                return false;
            }
        }



        public IEnumerable<Domaine.Entity.Membership> FindMembersByEmail(string emailToMatch, int pageIndex, int pageSize )
        {
            throw new NotImplementedException("FindMembersByEmail");
        }

        public IEnumerable<Domaine.Entity.Membership> FindMembersByName(string usernameToMatch, int pageIndex, int pageSize )
        {
            throw new NotImplementedException("FindMembersByName");
        }

        public IEnumerable<Domaine.Entity.Membership> GetPagedMembers(int pageIndex, int pageSize)
        {
            return this._memberShipRepository.GetPagedFullElements(pageIndex, pageSize);
        }

        public  int GetNumberOfUsersOnline()
        {
            throw new NotImplementedException("GetNumberOfUsersOnline");
        }
        
        public  string GetPassword(string username, string answer)
        {
            if (!this.EnablePasswordRetrieval)
                throw new NotSupportedException(Messages.PasswordHashedRetrieval);
            Domaine.Entity.Membership member = this._memberShipRepository.GetFilteredFullElements(u => u.User.UserName == username).FirstOrDefault();
            if (member == null) return null;

            var passwordFormat = member.PasswordFormat ;
            var passwordSalt = member.PasswordSalt ;
            var dbAnswer = member.PasswordAnswer ;
            if (!CheckAnswerPassword(member, answer, passwordFormat, passwordSalt, true))
            {
                this._memberShipRepository.Remove(member);
                this._memberShipRepository.UnitOfWork.Commit();
                return null;
            }
            member.FailedPasswordAnswerAttemptCount=0;
            member.FailedPasswordAttemptCount= 0;
            this._memberShipRepository.Remove(member);
            this._memberShipRepository.UnitOfWork.Commit();
            return UnEncodePassword(member.Password , passwordFormat);
        }



        public Domaine.Entity.Membership GetMemberByID(Guid id, bool userIsOnline)
        {

            Domaine.Entity.Membership member = this._memberShipRepository.GetFullElemnt(id);
             if (member == null) return null;
            if (userIsOnline)
            {
                member.User.LastActivityDate = DateTime.UtcNow;
                this._memberShipRepository.Remove(member);
                this._memberShipRepository.UnitOfWork.Commit();
            }
            return member;
                
        }
        public Domaine.Entity.Membership GetMemberByName(string username, bool userIsOnline)
        {
            Domaine.Entity.Membership member = this._memberShipRepository.GetFilteredFullElements(u => u.User.UserName == username).FirstOrDefault();  
            if (member == null) return null;

            if (userIsOnline)
            {
                member.User.LastActivityDate = DateTime.UtcNow;
                this._memberShipRepository.Remove(member);
                this._memberShipRepository.UnitOfWork.Commit();
            }
            return member;
        }



        



        public  string ResetPassword(string username, string answer)
        {
            throw new NotImplementedException("ResetPassword");
        }

        public  bool UnlockUser(string userName)
        {
            throw new NotImplementedException("UnlockUser");
        }

        public void UpdateUser(Domaine.Entity.Membership member)
        {
            throw new NotImplementedException("UpdateUser");
        }

        public  bool ValidateUser(string username, string password)
        {
            Domaine.Entity.Membership member = this._memberShipRepository.GetFilteredFullElements(u => u.User.UserName == username).FirstOrDefault();
            if (member == null) return false;
            if (!member.IsApproved) return false;

            var passwordFormat = member.PasswordFormat;
            var passwordSalt = member.PasswordSalt;
            bool check = CheckPassword(member, password, passwordFormat, passwordSalt, true, true, true);
            member.User.LastActivityDate = DateTime.UtcNow;
            this._memberShipRepository.Remove(member);
            this._memberShipRepository.UnitOfWork.Commit();
            return check;
        }
        #endregion 
        #endregion

        #region local

        string GetConfigStringValue(MembershipSection config, string Key, string Default)
        {

              
              string sValue = config.Providers[config.DefaultProvider].Parameters[Key];
            if (sValue == null)
                return Default;

            return sValue;
        }


        public bool GetConfigBooleanValue(MembershipSection config, string Key, bool Default)
          {
              string sValue = config.Providers[config.DefaultProvider].Parameters[Key];
              if (sValue == null)
                  return Default;

              bool result;
              if (bool.TryParse(sValue, out result))
                  return result;
              else
                  throw new LMSException(Messages.RequireBooleanError + "(" + Key + ")");

          }



        int GetConfigIntValue(MembershipSection config, string valueName, int defaultValue, bool zeroAllowed, int maxValueAllowed)
          {
              string sValue = config.Providers[config.DefaultProvider].Parameters[valueName];

              if (sValue == null)
                  return defaultValue;
              int iValue;
              if (!Int32.TryParse(sValue, out iValue))
              {
                  if (zeroAllowed)
                      throw new LMSException(Messages.NonNegativeIntegerError + "(" + valueName + ")");
                  throw new LMSException(Messages.MustBePositiveError + "(" + valueName + ")");
              }
              if (zeroAllowed && iValue < 0)
                  throw new LMSException(Messages.NonNegativeIntegerError + "(" + valueName + ")");
              if (!zeroAllowed && iValue <= 0)
                  throw new LMSException(Messages.MustBePositiveError + "(" + valueName + ")");
              if (maxValueAllowed > 0 && iValue > maxValueAllowed)
                  throw new LMSException(Messages.TooBigValueError + "(" + valueName + ")");
              return iValue;
          }
      
        
        Guid CreateMemberId(Guid userId)
        {
            Guid userKey=Guid.NewGuid();
            if (userId != null)
            {
                try
                {
                    var newkey = Guid.Parse(userId.ToString());
                    if (newkey != Guid.Empty)
                    {
                        var usr = this._memberShipRepository.Get(newkey);
                        if (usr != null)
                        {
                            throw new Exception(Messages.DuplicateProviderUserKey);
                        }
                       userKey= newkey;
                    }
                     
                }
                catch (Exception)
                {
                    throw new Exception(Messages.InvalidProviderUserKey);
                }

            }
            return userKey;
        }

        bool checkMinAlphaNumericPassword(string pwd, int minChars)
        {
            int count = 0;
            for (int i = 0; i < pwd.Length; i++)
                if (!char.IsLetterOrDigit(pwd, i))
                    count++;
            return (count >= minChars);
        }



         internal bool CheckPassword(Domaine.Entity.Membership member, string Password, MembershipPasswordFormat Format, string Salt, bool UpdateActivity, bool UpdateLogin, bool LockIsPossible)
         {

             if (member == null) return false;
             if (member.IsLockedOut) return false;

             var Hashed = EncodePassword(Password, Format, Salt);
             var storedPassword = member.Password;
             if (Hashed.Equals(storedPassword, StringComparison.OrdinalIgnoreCase))
             {
                 if (UpdateActivity)
                     member.User.LastActivityDate = DateTime.UtcNow;

                 if (UpdateLogin)
                     member.LastLoginDate =DateTime.UtcNow;

                 if ( LockIsPossible)
                 {
                     member.FailedPasswordAttemptCount = 0;
                     member.FailedPasswordAttemptWindowStart=new DateTime(1800, 1, 1);
                 }

                 return true;
             }
             else
             {
                 if (LockIsPossible)
                 {
                     var faileds = member.FailedPasswordAttemptCount + 1;
                     var failedOn = member.FailedPasswordAttemptWindowStart;

                     var utc = DateTime.UtcNow;
                     if (failedOn.AddMinutes(this.PasswordAttemptWindow) >= utc)
                         member.FailedPasswordAttemptCount= 1;
                     else
                         member.FailedPasswordAttemptCount=faileds;

                     member.FailedPasswordAttemptWindowStart= utc;
                     if (faileds >= this.MaxInvalidPasswordAttempts)
                     {
                         member.IsLockedOut=true;
                     }
                 }

                 return false;
             }
         }


         internal string EncodePassword(string pass, MembershipPasswordFormat passwordFormat, string salt)
         {
             if (passwordFormat == MembershipPasswordFormat.Clear)
             {
                 return pass;
             }
             byte[] bytes = Encoding.Unicode.GetBytes(pass);
             byte[] src = Convert.FromBase64String(salt);
             byte[] inArray = null;
             if (passwordFormat == MembershipPasswordFormat.Hashed)
             {
                 HashAlgorithm hashAlgorithm = this.GetHashAlgorithm();
                 if (hashAlgorithm is KeyedHashAlgorithm)
                 {
                     KeyedHashAlgorithm algorithm2 = (KeyedHashAlgorithm)hashAlgorithm;
                     if (algorithm2.Key.Length == src.Length)
                     {
                         algorithm2.Key = src;
                     }
                     else if (algorithm2.Key.Length < src.Length)
                     {
                         byte[] dst = new byte[algorithm2.Key.Length];
                         Buffer.BlockCopy(src, 0, dst, 0, dst.Length);
                         algorithm2.Key = dst;
                     }
                     else
                     {
                         int num2;
                         byte[] buffer5 = new byte[algorithm2.Key.Length];
                         for (int i = 0; i < buffer5.Length; i += num2)
                         {
                             num2 = Math.Min(src.Length, buffer5.Length - i);
                             Buffer.BlockCopy(src, 0, buffer5, i, num2);
                         }
                         algorithm2.Key = buffer5;
                     }
                     inArray = algorithm2.ComputeHash(bytes);
                 }
                 else
                 {
                     byte[] buffer6 = new byte[src.Length + bytes.Length];
                     Buffer.BlockCopy(src, 0, buffer6, 0, src.Length);
                     Buffer.BlockCopy(bytes, 0, buffer6, src.Length, bytes.Length);
                     inArray = hashAlgorithm.ComputeHash(buffer6);
                 }
             }
             else
             {
                 byte[] buffer7 = new byte[src.Length + bytes.Length];
                 Buffer.BlockCopy(src, 0, buffer7, 0, src.Length);
                 Buffer.BlockCopy(bytes, 0, buffer7, src.Length, bytes.Length);
                 inArray =  EncryptPassword(buffer7 );
                 
             }
             return Convert.ToBase64String(inArray);
         }


        private byte[] EncryptPassword(byte[] buffer )
        {
           
            RC2CryptoServiceProvider rc2CSP = new RC2CryptoServiceProvider();
            ICryptoTransform encryptor = rc2CSP.CreateEncryptor( );
            using (MemoryStream msEncrypt = new MemoryStream())
            {
                using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
                {
                    csEncrypt.Write(buffer, 0, buffer.Length);
                    csEncrypt.FlushFinalBlock();
                    return msEncrypt.ToArray();
                }
            }
        }


        private byte[] DecryptPassword(byte[] buffer)
        {
            RC2CryptoServiceProvider rc2CSP = new RC2CryptoServiceProvider();
            ICryptoTransform decryptor = rc2CSP.CreateDecryptor();
            using (MemoryStream msDecrypt = new MemoryStream(buffer))
            {
                using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
                {
                    List<Byte> bytes = new List<byte>();
                    int b;
                    do
                    {
                        b = csDecrypt.ReadByte();
                        if (b != -1)
                        {
                            bytes.Add(Convert.ToByte(b));
                        }
                    }
                    while (b != -1);
                    return  bytes.ToArray();
                }
            }
        }
        

         private HashAlgorithm GetHashAlgorithm()
         {
             if (this.s_HashAlgorithm != null)
             {
                 return HashAlgorithm.Create(this.s_HashAlgorithm);
             }
             string hashAlgorithmType = "SHA1";
              
             HashAlgorithm algorithm = HashAlgorithm.Create(hashAlgorithmType);
             if (algorithm == null)
             {
                 throw new LMSException(Messages.InvalidHashTypeError);
             }
             this.s_HashAlgorithm = hashAlgorithmType;
             return algorithm;
         }

         internal string GenerateSalt()
         {
             byte[] buf = new byte[SALT_SIZE_IN_BYTES];
             (new RNGCryptoServiceProvider()).GetBytes(buf);
             return Convert.ToBase64String(buf);
         }

         internal string EncodeAnswerPassword(string pass, MembershipPasswordFormat passwordFormat, string salt)
         {
             return EncodePassword(pass.ToLower().Trim(), passwordFormat, salt);
         }

         internal bool CheckAnswerPassword(Domaine.Entity.Membership member, 
                                                         string Answer, 
                                                        MembershipPasswordFormat Format, 
                                                        string Salt, bool LockIsPossible)
         {
             if (member.IsLockedOut) return false;

             var Hashed = EncodePassword(Answer.ToLower(), Format, Salt);
             if (Hashed.Equals(member.PasswordAnswer, StringComparison.OrdinalIgnoreCase))
             {
                 if ( LockIsPossible)
                 {
                     member.FailedPasswordAnswerAttemptCount=0;
                     member.FailedPasswordAnswerAttemptWindowStart=new DateTime(1800, 1, 1);
                 }

                 return true;
             }
             else
             {
                 if (LockIsPossible )
                 {
                     var faileds = member.FailedPasswordAnswerAttemptCount + 1;
                     var failedOn = member.FailedPasswordAnswerAttemptWindowStart ;

                     var utc = DateTime.UtcNow;
                     if (failedOn.AddMinutes(this.PasswordAttemptWindow) >= utc)
                         member.FailedPasswordAnswerAttemptCount= 1;
                     else
                         member.FailedPasswordAnswerAttemptCount=faileds;

                     member.FailedPasswordAnswerAttemptWindowStart=utc;
                     if (this.MaxInvalidPasswordAttempts >= faileds)
                     {
                         member.IsLockedOut=true;
                     }
                 }

                 return false;
             }
         }

         internal string UnEncodePassword(string pass, MembershipPasswordFormat passwordFormat)
         {
             switch (passwordFormat)
             {
                 case MembershipPasswordFormat.Clear:
                     return pass;
                 case MembershipPasswordFormat.Hashed:
                     throw new LMSException(Messages.PasswordHashedRetrieval);
                 default:
                     byte[] bIn = Convert.FromBase64String(pass);
                     byte[] bRet = DecryptPassword(bIn);
                     if (bRet == null)
                         return null;
                     return Encoding.Unicode.GetString(bRet);
             }
         }
        
        #region Validators

         protected virtual bool IsValidEmail(string email)
         {
             try
             {
                 var ValidEmail = new System.Net.Mail.MailAddress(email);
                 return true;
             }
             catch
             {
                 return false;
             }

         }


        #endregion
        #endregion
    }
}
